package com.whiteape.book.service;

import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

import androidx.annotation.Nullable;

import com.hwangjr.rxbus.RxBus;
import com.hwangjr.rxbus.annotation.Subscribe;
import com.hwangjr.rxbus.annotation.Tag;
import com.hwangjr.rxbus.thread.EventThread;
import com.whiteape.book.common.RxEvent;
import com.whiteape.book.common.WaConstants;
import com.whiteape.book.core.manager.MediaStorageManager;
import com.whiteape.book.core.manager.WebMediaManager;
import com.whiteape.book.model.bo.ChapterContentBo;
import com.whiteape.book.model.dto.CollectionMediaBean;
import com.whiteape.book.model.dto.DownloadTaskBean;
import com.whiteape.book.model.dto.MediaChapterBean;
import com.whiteape.book.model.dto.SiteSourceBean;
import com.whiteape.book.model.type.DownloadStatus;
import com.whiteape.book.model.type.MediaType;
import com.whiteape.book.net.RetrofitHelper;
import com.whiteape.book.ui.base.BaseService;
import com.whiteape.book.utils.DaoDbHelper;
import com.whiteape.book.utils.FileUtils;
import com.whiteape.book.utils.GsonUtils;
import com.whiteape.book.utils.LogUtils;
import com.whiteape.book.utils.URLUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import io.reactivex.Scheduler;
import io.reactivex.Single;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;

public class DownloadService extends BaseService {
    private static final int RETRY_COUNT = 3;
    private ExecutorService executor = Executors.newFixedThreadPool(3);
    private Scheduler scheduler = Schedulers.from(executor);
    List<DownloadTaskBean> downloadTaskBeanList;
    private Set<DownloadTaskBean> taskNeedToStopSet = new HashSet<>();
    private Set<DownloadTaskBean> taskNeedToStartSet = new HashSet<>();
    //已经存在于当前队列中的
    private Set<DownloadTaskBean> taskAlreadyInQueueSet = new HashSet<>();

    IDownloadListener listener;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new DownloadTask();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        RxBus.get().register(this);
        downloadTaskBeanList = MediaStorageManager.getInstance().getDownloadTaskAll();
        taskNeedToStartSet.clear();
        taskNeedToStopSet.clear();
        for (DownloadTaskBean downloadTaskBean : downloadTaskBeanList) {
            if (downloadTaskBean.getStatus() == DownloadStatus.STATUS_DOWNLOADING ||
                    downloadTaskBean.getStatus() == DownloadStatus.STATUS_WAIT) {
                taskNeedToStartSet.add(downloadTaskBean);
            }
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        RxBus.get().unregister(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return super.onStartCommand(intent, flags, startId);
    }


    //默认全部开始?靠rxjava里面的io线程池控制并发?
    private void startWork() {
        for (DownloadTaskBean downloadTaskBean : taskNeedToStartSet) {
            downloadTaskBean.setStatus(DownloadStatus.STATUS_WAIT);
            executor.execute(() -> download(downloadTaskBean));
        }
    }

    public void download(DownloadTaskBean downloadTaskBean) {
        if (taskNeedToStopSet.contains(downloadTaskBean)) {
            return;
        }
        List<MediaChapterBean> chapterList = downloadTaskBean.getMediaChapterList();
        if (chapterList == null || chapterList.size() == 0) {
            LogUtils.e("下载时找不到章节信息信息了。。");
            downloadTaskBean.setStatus(DownloadStatus.STATUS_ERROR);
            notifyDownloadTaskChanged(downloadTaskBean);
            return;
        }

        CollectionMediaBean collectionMediaBean = MediaStorageManager.getInstance().getShelfMedia(downloadTaskBean.getMediaId());
        if (collectionMediaBean == null) {
            LogUtils.e("下载时找不到media信息了。。");
            downloadTaskBean.setStatus(DownloadStatus.STATUS_ERROR);
            notifyDownloadTaskChanged(downloadTaskBean);
            return;
        }
        collectionMediaBean.__setDaoSession(DaoDbHelper.getInstance().getSession());
        SiteSourceBean siteSourceBean = collectionMediaBean.getSiteSourceBean();
        if (siteSourceBean == null) {
            //TODO 删除网源需要提示，如果当前有使用的网源，不能删除
            LogUtils.e("下载时找不到网源信息了，网源被删除了？");
            downloadTaskBean.setStatus(DownloadStatus.STATUS_ERROR);
            notifyDownloadTaskChanged(downloadTaskBean);
            return;
        }

        for (int i = downloadTaskBean.getCurrentChapter(); i < chapterList.size(); i++) {
            MediaChapterBean chapter = chapterList.get(i);
            if (MediaStorageManager.isChapterCached(siteSourceBean.getSiteType(), downloadTaskBean.getMediaId(), chapter)) {

                //TODO comic chapterCached?
                onOneChapterFinished(downloadTaskBean);
                continue;
            }
            download(siteSourceBean, downloadTaskBean, chapter);
        }
        if (downloadTaskBean.getCurrentChapter() >= downloadTaskBean.getMediaChapterList().size() - 1) {
            downloadTaskBean.setStatus(DownloadStatus.STATUS_FINISH);
        }
        notifyDownloadTaskChanged(downloadTaskBean);
    }

    private void download(SiteSourceBean siteSourceBean, DownloadTaskBean downloadTaskBean, MediaChapterBean chapter) {

        if (taskNeedToStopSet.contains(downloadTaskBean)) {
            return;
        }
        downloadTaskBean.setStatus(DownloadStatus.STATUS_DOWNLOADING);
        notifyDownloadTaskChanged(downloadTaskBean);
        CollectionMediaBean collectionMediaBean = MediaStorageManager.getInstance().getShelfMedia(downloadTaskBean.getMediaId());
        if (collectionMediaBean == null) {
            LogUtils.e("download but media is null");
            return;
        }
        if (collectionMediaBean.getMediaType() == MediaType.MEDIA_TYPE_NOVEL) {

            downloadNovel(siteSourceBean, downloadTaskBean, chapter);
        } else if (collectionMediaBean.getMediaType() == MediaType.MEDIA_TYPE_COMIC) {
            downloadComic(siteSourceBean, collectionMediaBean, downloadTaskBean, chapter);
        }

    }

    private void downloadNovel(SiteSourceBean siteSourceBean, DownloadTaskBean downloadTaskBean, MediaChapterBean chapter) {

        String mediaId = downloadTaskBean.getMediaId();
        Disposable disposable = WebMediaManager.getInstance()
                .getBookChapterContent(siteSourceBean, chapter.getLink())
                .retry(RETRY_COUNT)
//                    .compose(RxUtils::toSimpleSingle)
                .subscribe(chapterContentBoList -> {
                    StringBuilder sb = new StringBuilder();
                    for (ChapterContentBo chapterContentBo : chapterContentBoList) {
                        sb.append(chapterContentBo.getContent());

                    }

                    MediaStorageManager.getInstance()
                            .saveChapterInfo(mediaId, chapter.getName(), sb.toString());

                    onOneChapterFinished(downloadTaskBean);

                }, throwable -> {
                    //TODO 提示下载失败，中断下载
                    downloadTaskBean.setStatus(DownloadStatus.STATUS_ERROR);
                    notifyDownloadTaskChanged(downloadTaskBean);
                });
        addDisposable(disposable);
    }

    private void downloadComic(SiteSourceBean siteSourceBean, CollectionMediaBean collectionMediaBean, DownloadTaskBean downloadTaskBean, MediaChapterBean chapter) {
        String mediaId = downloadTaskBean.getMediaId();
        Disposable disposable = WebMediaManager.getInstance()
                .getComicChapterContent(siteSourceBean, collectionMediaBean, chapter)
                .retry(RETRY_COUNT)
//                    .compose(RxUtils::toSimpleSingle)
                .subscribe(chapterContentBoList -> {

                    String content = GsonUtils.obj2String(chapterContentBoList);
                    //先保存章节信息，章节信息里面是一个章节的图片信息
                    MediaStorageManager.getInstance().saveChapterInfo(mediaId, chapter.getName(), content);
                    //设置当前章节的图片总数
                    downloadTaskBean.setCurrentChapterPartTotal(chapterContentBoList.size());
                    notifyDownloadTaskChanged(downloadTaskBean);

                    if (chapterContentBoList.get(0).getLazyLoading()) {
                        List<Single<List<ChapterContentBo>>> singleList = new ArrayList<>();

                        for (ChapterContentBo contentBo : chapterContentBoList) {
                            singleList.add(WebMediaManager.getInstance().getComicContentLazy(siteSourceBean, collectionMediaBean, contentBo));
                        }
                        addDisposable(Single.merge(singleList)
                                .retry(RETRY_COUNT)
                                .subscribe(chapterContentBoList1 -> {
                                    if (chapterContentBoList1 == null || chapterContentBoList1.isEmpty()) {
                                        downloadTaskBean.setStatus(DownloadStatus.STATUS_ERROR);
                                        notifyDownloadTaskChanged(downloadTaskBean);
                                        return;
                                    }

                                    downloadPictureAndDoNotify(downloadTaskBean, chapter, chapterContentBoList1.get(0));

                                }, throwable -> {
                                    downloadTaskBean.setStatus(DownloadStatus.STATUS_ERROR);
                                    notifyDownloadTaskChanged(downloadTaskBean);

                                }, () -> onOneChapterFinished(downloadTaskBean)));

                    } else {
                        for (ChapterContentBo contentBo : chapterContentBoList) {
                            //直接下载url
                            downloadPictureAndDoNotify(downloadTaskBean, chapter, contentBo);

                        }
                        onOneChapterFinished(downloadTaskBean);
                    }


                }, throwable -> {
                    //TODO 提示下载失败，中断下载
                    downloadTaskBean.setStatus(DownloadStatus.STATUS_ERROR);
                    notifyDownloadTaskChanged(downloadTaskBean);
                });
        addDisposable(disposable);
    }

    //下载完一章，更新数据
    synchronized private void onOneChapterFinished(DownloadTaskBean downloadTaskBean) {

        int indexNow = downloadTaskBean.getCurrentChapter() < downloadTaskBean.getMediaChapterList().size() ?
                downloadTaskBean.getCurrentChapter() + 1 : downloadTaskBean.getMediaChapterList().size() - 1;
        downloadTaskBean.setCurrentChapter(indexNow);

        MediaStorageManager.getInstance()
                .saveDownloadTask(downloadTaskBean);

        notifyDownloadTaskChanged(downloadTaskBean);
    }

    private void downloadPictureAndDoNotify(DownloadTaskBean downloadTaskBean, MediaChapterBean chapter, ChapterContentBo contentBo) {
        String mediaId = downloadTaskBean.getMediaId();
        String url = contentBo.getContent();

        //直接下载url
        boolean downloadPicRet = downloadOnePicture(mediaId, chapter.getId(), contentBo.getCurPartNum(), url);
        if (downloadPicRet) {
            //
            downloadTaskBean.setCurrentChapterCurPart(contentBo.getCurPartNum());
            updateComicChapterContent(mediaId, chapter, contentBo);
            notifyDownloadTaskChanged(downloadTaskBean);
        } else {
            //TODO 下载中断，类似暂停

        }
    }

    //retrofit下载
    private boolean downloadOnePicture(String mediaId, String chapterId, int partNum, String url) {
        try {
            ResponseBody responseBody = RetrofitHelper.getInstance().getHttpApiImpl(URLUtils.getBaseUrl(url)).download(url).execute().body();
            String folderName = mediaId + File.separator + chapterId;
            MediaStorageManager.saveComicPic(folderName, partNum + "", responseBody.byteStream());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    //懒加载的图片信息更新
    public void updateComicChapterContent(String mediaId, MediaChapterBean chapter, ChapterContentBo chapterContentBo) {
        List<ChapterContentBo> boList = MediaStorageManager.getInstance().getComicChapterInfoBean(mediaId, chapter.getName());
        if (boList == null) {
            return;
        }
        for (ChapterContentBo bo : boList) {
            if (!chapterContentBo.getCurPartNum().equals(bo.getCurPartNum())) {
                continue;
            }
            bo.setLazyLoading(false);
            String folderName = mediaId + File.separator + chapter.getId();
            String fileName = chapterContentBo.getCurPartNum() + "";
            File file = FileUtils.getFile(WaConstants.MEDIA_CACHE_PATH + folderName
                    + File.separator + fileName + FileUtils.SUFFIX_WAP);
            bo.setContent(file.getAbsolutePath());
            break;
        }

        String content = GsonUtils.obj2String(boList);
        MediaStorageManager.getInstance().saveChapterInfo(
                mediaId, chapter.getName(), content);

    }

    private void notifyDownloadTaskChanged(DownloadTaskBean downloadTaskBean) {
        listener.onDownloadStatusChanged(downloadTaskBean);

    }

    class DownloadTask extends Binder implements IDownloadTask {

        @Override
        public void download() {

        }

        public void startWork() {
            DownloadService.this.startWork();

        }

        @Override
        public void setDownloadListener(IDownloadListener listener) {
            DownloadService.this.listener = listener;
        }

        @Override
        public List<DownloadTaskBean> getDownloadTaskBeanList() {
            return downloadTaskBeanList;
        }

    }

    public interface IDownloadTask {
        void download();

        void startWork();

        void setDownloadListener(IDownloadListener listener);

        List<DownloadTaskBean> getDownloadTaskBeanList();

    }

    public interface IDownloadListener {
        void onDownloadStatusChanged(DownloadTaskBean task);
    }


    @Subscribe(thread = EventThread.IO,
            tags = {@Tag(RxEvent.DOWNLOAD_TASK_ADD)})
    public void addDownloadTaskBean(DownloadTaskBean bean) {
        LogUtils.d("添加下载项, task name = " + bean.getTaskName());
        taskNeedToStopSet.remove(bean);
        taskNeedToStartSet.add(bean);
        if (executor.isShutdown() || executor.isTerminated()) {
            return;
        }
        executor.execute(() -> download(bean));
    }

    @Subscribe(thread = EventThread.IO,
            tags = {@Tag(RxEvent.DOWNLOAD_TASK_REMOVED)})
    public void batchRemoveTask(ArrayList<DownloadTaskBean> taskBeanList) {
        for (DownloadTaskBean bean : taskBeanList) {
            bean.setStatus(DownloadStatus.STATUS_PAUSE);
        }
        taskNeedToStartSet.removeAll(taskBeanList);
        taskNeedToStopSet.addAll(taskBeanList);
    }

    @Subscribe(thread = EventThread.IO,
            tags = {@Tag(RxEvent.DOWNLOAD_STATUS_CHANGED)})
    public void onDownloadTaskStatusChanged(DownloadTaskBean downloadTaskBean) {
        LogUtils.d("DownloadService: onDownloadTaskStatusChanged taskName = " + downloadTaskBean.getTaskName());
        if (downloadTaskBean.getStatus() == DownloadStatus.STATUS_PAUSE) {
            taskNeedToStartSet.remove(downloadTaskBean);
            taskNeedToStopSet.add(downloadTaskBean);
        } else if (downloadTaskBean.getStatus() == DownloadStatus.STATUS_DOWNLOADING) {
            addDownloadTaskBean(downloadTaskBean);
        }

    }

}
